package br.unesp.rc.rafaelt.server.resources;

import java.util.ArrayList;

import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import br.unesp.rc.rafaelt.server.businnes.services.AuthorService;
import br.unesp.rc.rafaelt.server.model.bean.Author;
import br.unesp.rc.rafaelt.server.model.bean.AuthorList;

@Controller
@RequestMapping(value = "/authors")
public class AuthorResource {
	private static final Logger LOGGER = LoggerFactory.getLogger(AuthorResource.class);

	@Autowired
	private AuthorService authorService;

	@RequestMapping(method = RequestMethod.POST)
	@ResponseBody
	public Author create(@RequestBody Author author) {
		LOGGER.info("Creating new author {}", author);

		return authorService.create(author);
	}

	@RequestMapping(value = "/{authorId}", method = RequestMethod.GET)
	@ResponseBody
	public Author read(@PathVariable(value = "authorId") long authorId) {
		LOGGER.info("Reading author with id {}", authorId);

		Author author = authorService.read(authorId);

		Validate.isTrue(author != null, "Unable to find author with id: " + authorId);

		return author;
	}

	@RequestMapping(value = "/{authorId}", method = RequestMethod.PUT)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void update(@PathVariable(value = "authorId") long authorId, @RequestBody Author author) {
		LOGGER.info("Updating author with id {} with {}", authorId, author);

		Validate.isTrue(authorId == author.getId(), "authorId doesn't match URL authorId: " + author.getId());

		authorService.update(author);
	}

	@RequestMapping(value = "/{authorId}", method = RequestMethod.DELETE)
	@ResponseStatus(value = HttpStatus.NO_CONTENT)
	public void delete(@PathVariable(value = "authorId") long authorId) {
		LOGGER.info("Deleting author with id {}", authorId);

		authorService.delete(authorId);
	}

	@RequestMapping(method = RequestMethod.GET)
	@ResponseBody
	public AuthorList list() {
		LOGGER.info("Listing authors");

		return new AuthorList(new ArrayList<Author>(authorService.list()));
	}

	@ExceptionHandler(IllegalArgumentException.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)
	@ResponseBody
	public String handleClientErrors(Exception ex) {
		LOGGER.error(ex.getMessage(), ex);
		return ex.getMessage();
	}

	@ExceptionHandler(Exception.class)
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	@ResponseBody
	public String handleServerErrors(Exception ex) {
		LOGGER.error(ex.getMessage(), ex);
		return ex.getMessage();
	}
}
